﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Runtime.InteropServices;
using ProtHandlers;
using ConnectionControl;
using pokerServer.ProtHandlers;

using pokerServer.GameManagment.GameTools;

namespace ConnectionControl
{
	using pokerServer;

	using Usermanagment.DBConnection;
	public class ClientConnection
	{

		private Boolean flag, threadAlive, loggedIn;
		private Thread t;
		private ConnectionManag cm;
		private TcpClient s;
		private String name = " ", exMsg = "";
		private int chips = 0,tableId = -1 , seatId =-1;
		private StreamReader rm;
		private StreamWriter sm;
		private ProtHandler ph;
		private ManualResetEvent mre;
		private DBConnect dbc;
		public Player myPlayer;

		public ClientConnection(ConnectionManag cm, TcpClient s)
		{
			t = new Thread(new ThreadStart(work));
			//	t.IsBackground = true;
			this.s = s;
			this.s.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
			this.cm = cm;
			mre = new ManualResetEvent(false);
			flag = true;
			loggedIn = false;
		//	Wind32.AllocConsole();
		}

		public void work()
		{
			threadAlive = true;
			String msg = " ";
			NetworkStream ns = new NetworkStream(s.Client);			
			rm = new StreamReader(s.GetStream());
			sm = new StreamWriter(s.GetStream());
			ph = new ProtHandler(this, this.cm);
			dbc = new DBConnect();			
			try
			{				
				while (this.flag)
				{
					if(ns.DataAvailable)
						msg = rm.ReadLine();				
					if (msg != null && !msg.Equals(" "))
					{
						pokerServer.FilePrint.DebugPrint.writeBugtofile("IN:"+msg+"\r\n");
						String[] t = msg.Split(' ');
						ph.assignCommand(t);
						String temp = ph.work();
						if (!String.IsNullOrWhiteSpace(temp)) {
							sm.WriteLine(temp);
						}
						sm.Flush();
						pokerServer.FilePrint.DebugPrint.writeBugtofile("OUT:" + temp+"\r\n");
						if (ph.toClose())
							break;
						msg = " ";
					}
					if (this.conDead())
						break;
					Thread.Sleep(200);
				}

			}
			catch (SocketException e)
			{
				Console.WriteLine(e.StackTrace);
				Console.WriteLine("Problem in Thread Catch :" + e.Message);
				exMsg = e.Message;
			}
			finally
			{
				threadAlive = false;
				mre.Set();
				this.close();
				System.Console.WriteLine("Thread ended!");

				/*
				 if (this.myPlayer != null && this.myPlayer.table != null) {
					this.myPlayer.table.removePlayer(this.myPlayer);
					}
				*/
			}
		}

		private Boolean conDead()
		{
			Boolean flag = false;
			if (this.s.Client.Poll(0, SelectMode.SelectRead))
			{
				byte[] buff = new byte[1];
				if (this.s.Client.Receive(buff, SocketFlags.Peek) == 0)
				{
					flag = true;
				}
			}
			return flag;
		}

		public void startWork()
		{
			t.Start();
		}

		public void SendMsg(String s)
		{
			try
			{
				if (sm != null)
				{
					sm.WriteLine(s);
					sm.Flush();
				}
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
		}

		public Boolean isLoggedin
		{
			get
			{
				return this.loggedIn;
			}
			set
			{
				this.loggedIn = value;
			}
		}

		public String getStatuses()
		{
			return exMsg + " Thread Running: " + threadAlive + ", ConAlive:" + s.Connected;
		}

		public Boolean isAlive()
		{
			return this.flag;
		}

		public Boolean stopWorking()
		{
			this.flag = false;
			this.SendMsg("SYSTEMCLOSE");
			Boolean ans = mre.WaitOne(10000);
			Console.WriteLine("MRE:" + ans);
			return ans;
		}

		public int seatID
		{
			get
			{
				return this.seatId;
			}
			set
			{
				this.seatId = value;
			}
		}

		public int tableID
		{
			set
			{
				this.tableId = value;
			}

			get
			{
				return this.tableId;
			}
		}

		private void close()
		{
			if (this.loggedIn)
				this.cm.remove(this.name);
			else			
				this.cm.removeTemp(this);
			this.rm.Close();
			this.sm.Close();
			this.s.Close();
			this.dbc.closeConnection();
		}

		public String conName
		{
			get
			{
				return this.name;
			}
			set
			{
				this.name = value;
			}
		}

		public int conChips
		{
			set
			{
				this.chips = value;
			}
			get
			{
				return this.chips;
			}

		}


		public DBConnect getDBC()
		{
			return this.dbc;
		}
	}
}
